package com.nq.service.impl;

/**

 * 开发者----股牛网络

 * 联系TG：gncms

 */
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nq.activaity.dto.LotteryInfoResp;
import com.nq.activaity.dto.LotteryResp;
import com.nq.activaity.dto.ReceivingResp;
import com.nq.activaity.entity.*;
import com.nq.common.ServerResponse;
import com.nq.common.State;
import com.nq.common.UserIntegralTypeEnum;
import com.nq.dao.*;
import com.nq.dao.activaity.*;
import com.nq.fund.vo.StFundKlineVo;
import com.nq.pojo.*;
import com.nq.pojo.vo.FundsApplyVo;
import com.nq.service.*;
import com.nq.utils.*;
import com.nq.utils.redis.CookieUtils;
import com.nq.utils.redis.JsonUtil;
import com.nq.utils.redis.RedisShardedPoolUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 配资申请
 * @author lr
 * @date 2020/07/24
 */
@Service("LotteryService")
public class LotteryServiceImpl implements LotteryService {
    private static final Logger log = LoggerFactory.getLogger(LotteryServiceImpl.class);

    @Resource
    private IUserService iUserService;
    @Resource
    private StCompanyActPrizeMapper companyActPrizeMapper;
    @Resource
    private StMbrLotteryPrizeMapper lotteryPrizeMapper;
    @Resource
    private StUserIntegralRecordMapper userIntegralRecordMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserCashDetailMapper userCashDetailMapper;
    @Resource
    private StMbrAddressMapper mbrAddressMapper;
    @Resource
    private StMbrLotteryPrizeShipmentMapper mbrLotteryPrizeShipmentMapper;
    @Resource
    private StLotterySettingsMapper lotterySettingsMapper;

    @Resource
    private StUserSpecifiedPrizeMapper userSpecifiedPrizeMapper;



    @Override
    @Transactional
    public ServerResponse execute(HttpServletRequest request) {

        Date now = new Date();

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        QueryWrapper<StLotterySettings> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", State.STATE_0);
        List<StLotterySettings> stLotterySettings = lotterySettingsMapper.selectList(queryWrapper);
        if (null == stLotterySettings || stLotterySettings.isEmpty()) {
            return ServerResponse.createByErrorMsg("Lottery configuration does not exist !");
        }

        StLotterySettings lotterySettings = stLotterySettings.get(0);
        Date beginTime = lotterySettings.getBeginTime();
        Date endTime = lotterySettings.getEndTime();

        // 获取当前时间
        Date currentTime = new Date();
        DateTime time = new DateTime(currentTime);

        // 判断抽奖有效期
        // 开始时间
        DateTime aaBefore = new DateTime(beginTime);
        //  结束时间
        DateTime bbBefore = new DateTime(endTime);
        if(time.before(aaBefore) || time.after(bbBefore)) {
            return ServerResponse.createByErrorMsg("The lucky draw is not valid !");
        }

        // 判断每日抽奖次数
        Integer count = lotterySettings.getCount();

        // 查询用户当天抽奖次数
        Integer lotteryCount = lotteryPrizeMapper.queryLotteryCurrentDayByUserId(user.getId());
        if (lotteryCount >= count) {
            return ServerResponse.createByErrorMsg("You have used up the number of Raffles today !");
        }


        Integer consumption = lotterySettings.getIntegral();
        if (null == consumption) {
            consumption = 0;
        }
        // 消耗积分
        BigDecimal integral = new BigDecimal(consumption);

        // 用户积分数量
        BigDecimal enableFutAmt = user.getEnableFutAmt();
        if (enableFutAmt.compareTo(integral) < 0) {
            return ServerResponse.createByErrorMsg("You Don't have enough points to enter the lucky draw !");
        }

        // 增加积分记录
        StUserIntegralRecord record = new StUserIntegralRecord();
        record.setUserId(user.getId());
        record.setIncome(StUserIntegralRecord.EXPENDITURE_TYPE);
        record.setCreateBy(user.getNickName());
        record.setIntegralNum(integral);
        record.setIntegralNumBefore(enableFutAmt);


        // 用户剩余积分
        BigDecimal residualIntegral = enableFutAmt.subtract(integral);

        // 活动奖品
        LambdaQueryWrapper<StCompanyActPrize> actPrizeLqw = new LambdaQueryWrapper<>();
        actPrizeLqw.eq(StCompanyActPrize::getStatus, State.STATE_0)
                .orderByAsc(StCompanyActPrize::getDisplayNo);
        List<StCompanyActPrize> prizeList = companyActPrizeMapper.selectList(actPrizeLqw);
        if (null == prizeList || prizeList.isEmpty()) {
            return ServerResponse.createByErrorMsg("Insufficient surplus prizes for activitiesw !");
        }

        // 开始抽奖
        Integer index = this.lottery(prizeList);
        if (null == index) {
            return ServerResponse.createByErrorMsg("It's too late. The prizes have been robbed !");
        }

        // 是否是指定奖品类型
        Integer isSpecified = 0;
        StCompanyActPrize prize = new StCompanyActPrize();
        // 查询是否设置的指定奖品
        StUserSpecifiedPrize specifiedPrize = userSpecifiedPrizeMapper.queryPrizeByUserId(user.getId());
        if (null != specifiedPrize) {
            String prizeId = specifiedPrize.getPrizeId();
            prize = companyActPrizeMapper.selectById(prizeId);

            // 将设置指定奖品状态设置为已使用
            StUserSpecifiedPrize updatePrize = new StUserSpecifiedPrize();
            updatePrize.setId(specifiedPrize.getId());
            updatePrize.setEffectiveStatus(StUserSpecifiedPrize.EFFECTIVE_STATUS_USED);
            userSpecifiedPrizeMapper.updateById(updatePrize);

            isSpecified = 1;

        }else {
            prize = prizeList.get(index);
            isSpecified = 0;
        }


        String prizeId = prize.getId();
        String prizeTitle = prize.getPrizeTitle();
        String prizePic = prize.getPrizePic();
        // 当类型为现金和积分时 表示数量
        String prizeCode = prize.getPrizeCode();

        String type = prize.getType();
        Integer isPrize = StCompanyActPrize.NO_PRIZE_TYPE.equals(type) ? 0 : 1;

        StMbrLotteryPrize lotteryPrize = new StMbrLotteryPrize();
        lotteryPrize.setUserId(user.getId())
                .setUserNick(user.getNickName())
                .setPrizeId(prizeId)
                .setIsPrize(isPrize)
                .setStatus(StCompanyActPrize.IS_PRIZE_N)
                .setPrizeType(type)
                .setPrizeTitle(prizeTitle)
                .setPrizePic(prizePic)
                .setCreateTime(new Date())
                .setIsSpecified(isSpecified)
                .setReceiveChannel(type);

        // 没中奖或者奖品类型为现金或者积分类型的直接领取
        if (!StCompanyActPrize.ENTITY_POST_TYPE.equals(type)) {
            lotteryPrize.setStatus(StCompanyActPrize.IS_PRIZE_Y)
                    .setReceiveTime(now);
        }

        lotteryPrizeMapper.insert(lotteryPrize);

        // 更新用户积分
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setEnableFutAmt(residualIntegral);
        this.userMapper.updateByPrimaryKeySelective(updateUser);

        record.setReferId(lotteryPrize.getId());
        record.setIntegralNumAfter(residualIntegral);
        record.setCreateTime(now);
        record.setType(UserIntegralTypeEnum.LUCKY_DRAW_CONSUMPTION.getDesc());
        userIntegralRecordMapper.insert(record);


        // 判断中奖类型为现金或者积分类型的直接领取
        if (StCompanyActPrize.CASH.equals(type)) {
            BigDecimal enableAmt = user.getEnableAmt();
            // 中奖金额
            BigDecimal jackpotAmt = new BigDecimal(prizeCode);

            BigDecimal reckon_enable = enableAmt.add(jackpotAmt);
            user.setEnableAmt(reckon_enable);
            int updateUserCount = this.userMapper.updateByPrimaryKeySelective(user);

            if (updateUserCount > 0) {
                log.info("用户"+user.getId()+"抽奖, 中现金奖励" + jackpotAmt);
                UserCashDetail ucd = new UserCashDetail();
                ucd.setPositionId(lotteryPrize.getId());
                ucd.setAgentId(user.getAgentId());
                ucd.setAgentName(user.getAgentName());
                ucd.setUserId(user.getId());
                ucd.setUserName(user.getRealName());
                ucd.setDeType("lucky draw");
                ucd.setDeAmt(jackpotAmt);
                ucd.setDeSummary("Take part in the lucky draw and win the cash prize" + jackpotAmt);
                ucd.setAddTime(new Date());
                ucd.setIsRead(Integer.valueOf(0));
                userCashDetailMapper.insert(ucd);

            }
        }
        if (StCompanyActPrize.INTEGRAL.equals(type)) {
            // 更新用户积分
            User newUser = userMapper.selectByPrimaryKey(user.getId());
            if (null != newUser) {

                BigDecimal newEnableFutAmt = newUser.getEnableFutAmt();
                // 中奖积分
                BigDecimal jackpotIntegral = new BigDecimal(prizeCode);
                BigDecimal finallyIntegral = newEnableFutAmt.add(jackpotIntegral);

                User lotteryUser = new User();
                lotteryUser.setId(user.getId());
                lotteryUser.setEnableFutAmt(finallyIntegral);
                this.userMapper.updateByPrimaryKeySelective(lotteryUser);

                StUserIntegralRecord prizeInt = new StUserIntegralRecord();
                prizeInt.setUserId(user.getId());
                prizeInt.setCreateBy(user.getNickName());
                prizeInt.setIncome(StUserIntegralRecord.INCOME_TYPE);
                prizeInt.setIntegralNum(jackpotIntegral);
                prizeInt.setIntegralNumBefore(newEnableFutAmt);
                prizeInt.setIntegralNumAfter(finallyIntegral);
                prizeInt.setCreateTime(now);
                prizeInt.setType(UserIntegralTypeEnum.LUCKY_DRAW_JACKPOT.getDesc());
                record.setReferId(lotteryPrize.getId());
                userIntegralRecordMapper.insert(prizeInt);
            }
        }


        LotteryResp resp = new LotteryResp();
        resp.setIsPrize(isPrize);
        resp.setPrizeId(prizeId);
        resp.setType(type);
        resp.setPrizeTitle(prizeTitle);
        resp.setPrizePic(prizePic);
        resp.setLotteryPrizeId(lotteryPrize.getId());
        return ServerResponse.createBySuccess(resp);
    }

    @Override
    public ServerResponse receiving(String name, String tel, String addressDetail, HttpServletRequest request) {

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }


        if (StringUtils.isBlank(name)) {
            return ServerResponse.createByErrorMsg("Parameter error [name]");
        }
        if (StringUtils.isBlank(tel)) {
            return ServerResponse.createByErrorMsg("Parameter error [tel]");
        }
        if (StringUtils.isBlank(addressDetail)) {
            return ServerResponse.createByErrorMsg("Parameter error [addressDetail]");
        }


        Integer userId = user.getId();
        StMbrAddress mbrAddress = mbrAddressMapper.queryByUserId(userId);
        if (null != mbrAddress) {
            StMbrAddress updateAddress = new StMbrAddress();
            updateAddress.setId(mbrAddress.getId());
            updateAddress.setName(name);
            updateAddress.setTel(tel);
            updateAddress.setAddressDetail(addressDetail);
            mbrAddressMapper.updateById(updateAddress);
            return ServerResponse.createBySuccess();
        }


        StMbrAddress address = new StMbrAddress();
        address.setAddressDetail(addressDetail);
        address.setName(name);
        address.setTel(tel);
        address.setUserId(userId);
        // 新增的默认设置为默认
        address.setIsDefault("1");
        address.setDelFlag(0);
        mbrAddressMapper.insert(address);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse queryReceiving(HttpServletRequest request) {
        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        Integer userId = user.getId();
        StMbrAddress mbrAddress = mbrAddressMapper.queryByUserId(userId);
        ReceivingResp resp = new ReceivingResp();
        if (null != mbrAddress) {
            resp.setHaveAddress(1);
            resp.setMbrAddress(mbrAddress);
        }else {
            resp.setHaveAddress(0);
            resp.setMbrAddress(new StMbrAddress());
        }
        return ServerResponse.createBySuccess(resp);
    }

    @Override
    public ServerResponse addPost(Integer lotteryPrizeId, HttpServletRequest request) {

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        Integer userId = user.getId();
        StMbrAddress mbrAddress = mbrAddressMapper.queryByUserId(userId);
        if (null == mbrAddress) {
            return ServerResponse.createByErrorMsg("The receiving address does not exist !");
        }

        StMbrLotteryPrize prize = lotteryPrizeMapper.selectById(lotteryPrizeId);
        if (null == prize) {
            return ServerResponse.createByErrorMsg("No record exists !");
        }

        Integer prizeUserId = prize.getUserId();
        if (!prizeUserId.equals(userId)) {
            return ServerResponse.createByErrorMsg("You can not receive the prize, the owner is " + user.getNickName());
        }

        String prizeType = prize.getPrizeType();
        if (!StCompanyActPrize.ENTITY_POST_TYPE.equals(prizeType)) {
            return ServerResponse.createByErrorMsg("Wrong type of prize !");
        }

        StMbrLotteryPrizeShipment shipment = new StMbrLotteryPrizeShipment();
        shipment.setLotteryPrizeId(lotteryPrizeId);
        shipment.setUserId(userId);
        shipment.setAddressId(mbrAddress.getId());
        shipment.setState("0");
        shipment.setDelFlag(0);
        mbrLotteryPrizeShipmentMapper.insert(shipment);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse winningRecord(Integer pageNum, Integer pageSize, HttpServletRequest request) {

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        Integer userId = user.getId();

        PageHelper.startPage(pageNum, pageSize);
        List<StMbrLotteryPrize> list = lotteryPrizeMapper.queryListByUserId(userId);

        PageInfo pageInfo = new PageInfo(list);
        pageInfo.setList(list);
        return ServerResponse.createBySuccess(pageInfo);
    }

    @Override
    public ServerResponse lotteryInfo(HttpServletRequest request) {
        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        // 用户积分
        BigDecimal enableFutAmt = user.getEnableFutAmt();

        QueryWrapper<StLotterySettings> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", State.STATE_0);
        List<StLotterySettings> stLotterySettings = lotterySettingsMapper.selectList(queryWrapper);
        if (null == stLotterySettings || stLotterySettings.isEmpty()) {
            return ServerResponse.createByErrorMsg("Lottery configuration does not exist !");
        }

        StLotterySettings lotterySettings = stLotterySettings.get(0);

        // 每次抽奖消耗的积分
        Integer integral = lotterySettings.getIntegral();

        String lotteryRules = lotterySettings.getLotteryRules();

        LotteryInfoResp infoResp = new LotteryInfoResp();
        infoResp.setLotteryRules(lotteryRules);
        infoResp.setUserIntegral(enableFutAmt.intValue());
        infoResp.setConIntegral(integral);
        return ServerResponse.createBySuccess(infoResp);
    }

    @Override
    public ServerResponse prizesList(HttpServletRequest request) {

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        QueryWrapper<StCompanyActPrize> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", State.STATE_0);
        List<StCompanyActPrize> companyActPrizes = companyActPrizeMapper.selectList(queryWrapper);
        return ServerResponse.createBySuccess(companyActPrizes);
    }


    private Integer lottery(List<StCompanyActPrize> prizes) {
        //总的概率区间
        float totalPro = 0f;
        //存储每个奖品新的概率区间
        List<Float> proSection = new ArrayList<Float>();
        proSection.add(0f);

        //遍历每个奖品，设置概率区间，总的概率区间为每个概率区间的总和
        for (StCompanyActPrize prize : prizes) {
            //每个概率区间为奖品概率乘以100（把三位小数转换为整）
            totalPro += prize.getLotteryRate().floatValue() * 100;
            proSection.add(totalPro);
        }

        if((int) totalPro == 0) {
            return null;
        }

        //获取总的概率区间中的随机数
        Random random = new Random();
        float randomPro = (float) random.nextInt((int) totalPro);
        //判断取到的随机数在哪个奖品的概率区间中
        for (int i = 0, size = proSection.size(); i < size; i++) {
            if (randomPro >= proSection.get(i) && randomPro < proSection.get(i + 1)) {
                return i;
            }
        }
        return null;
    }

}
